在 Ruby 的程式語言裡實體變數是一種以 @ 符號為開頭的變數。
@fruit
實體變數屬於物件導向程式的一部分,這些物件有屬於自己儲存資料的空間。
物件可以:
做事情,因為有方法可以使用
知道事情,因為可以儲存資料
如果有一個水果類別,而使用者想要知道是什麼類型的水果、顏色重量等等。所有的標籤變成實體變數後會像這樣@color
、@type
、 @weight
。
在類別裡定義實體變數。假設說有一個咖啡機的類別,咖啡機需要水所以要知道需要多少水。
class CoffeeMachine
def initialize
@water = 100
end
end
@water
就是實體變數,假設 100 是這個實體變數的初始值。現在建立一個 “make_coffee” 方法,這樣會減少在水的量
class CoffeeMachine
def initialize
@water = 100
end
def make_coffee
@water -= 10
end
end
注意剛剛建立的咖啡機物件有自己的@water
值,如果有十台咖啡機那每一台都會有屬於自己的@water
。
如果無法讀取實體變數的的值,那實體變數就並不是這麼的好用。
可以這樣讀取:
class CoffeeMachine
def initialize
@water = 50
end
def print_water_level
puts "Water Level: #{@water}"
end
end
machine = CoffeeMachine.new
machine.print_water_level
# Water Level: 50
print_water_level 方法使用 @water 來印出值。
會許有注意到從類別外無法存取實體變數,就像其他的物件一樣被保護起來。
machine = CoffeeMachine.new
machine.water
# NoMethodError: undefined method `water' for #<CoffeeMachine:0x2d0a530>
machine.@water
# SyntaxError: unexpected tIVAR, expecting '('
但是在某些例子會需要存取實體變數,可以這樣做:
class CoffeeMachine
def initialize
@water = 100
end
def water
@water
end
end
machine = CoffeeMachine.new
machine.water
# 100
class CoffeeMachine
attr_reader :water
def initialize
@water = 100
end
end
machine = CoffeeMachine.new
machine.water
# 100
這兩段程式碼幾乎沒有什麼不同,唯一的差別是 ruby 幫你做事&建立一個 water 方法。使用實體變數需要注意的是:
為定義的實體變數永遠會回傳 nil
實體變數並不是一定要建立 initialize 方法,但是 initialize 方法可以建立初始值
有進階的方法可以存取實體變數像是 instance_variable_get 說樹狀況下應避免使用
另外可以檢查有什麼實體變數可以使用:
machine.instance_variables
# [:@water]
最重要的一件事,在 ruby 裡實體變數通常都是在 controller 與 views 之間分享資料。